#ifndef FS_INC
#define FS_INC

#define _GNU_SOURCE

#include <dirent.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#ifdef _WIN32
#define MKDIR(d, s) mkdir(d)
#else
#define MKDIR(d, s) mkdir(d, s)
#endif

/**
 * @brief remove path, file or directory
 * @param path to remove
 * @return 0 if success, -1 if error
 */
static int __platform_remove(const char* path);

/**
 * @brief rename path
 * @param path src
 * @param new_path to rename
 * @return 0 if success, -1 if error
 */
static int __platform_rename(const char* path, const char* new_path);

/**
 * @brief create directory
 * @param path to create
 * @return 0 if success, -1 if error
 * @return
 */
static int __platform_mkdir(const char* path);

/**
 * @brief check if path is a directory
 * @param path to check
 * @return 0 if path is a directory, -1 if not
 */
static int __platform_isDir(const char* path);

/**
 * @brief get time
 * @param path to get time
 * @return time
 */
static time_t __platform_time(const char* path);

#if 1
static int __platform_remove(const char* path) {
  struct stat path_stat;

  // 检查路径是否存在
  if (stat(path, &path_stat) != 0) {
    return 0;  // 路径不存在或无法访问
  }

  // 如果是普通文件或链接，直接删除
  if (!S_ISDIR(path_stat.st_mode)) {
    return unlink(path);
  }

  // 如果是目录，需要递归删除其内容
  DIR* dir = opendir(path);
  if (dir == NULL) {
    return -1;
  }

  struct dirent* entry;
  int result = 0;

  // 遍历目录中的所有项
  while ((entry = readdir(dir)) != NULL && result == 0) {
    // 跳过当前目录和父目录
    if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
      continue;
    }

    // 构造完整路径
    char* full_path;
    size_t path_len = strlen(path);
    size_t name_len = strlen(entry->d_name);

    full_path = malloc(path_len + name_len + 2);  // +1 for '/', +1 for '\0'
    if (full_path == NULL) {
      result = -1;
      break;
    }

    // 使用memcpy和snprintf替代strcpy和strcat
    memcpy(full_path, path, path_len);
    if (full_path[path_len - 1] != '/') {
      full_path[path_len] = '/';
      memcpy(full_path + path_len + 1, entry->d_name, name_len + 1);
    } else {
      memcpy(full_path + path_len, entry->d_name, name_len + 1);
    }

    // 递归删除子项
    result = __platform_remove(full_path);
    free(full_path);
  }

  closedir(dir);

  // 如果目录内容删除成功，删除目录本身
  if (result == 0) {
    result = rmdir(path);
  }

  return result;
}

static int __platform_rename(const char* path, const char* new_path) {
  return rename(path, new_path);
}

static int __platform_mkdir(const char* path) {
  if (path == NULL) {
    return -1;
  }

  char* dir_path = strdup(path);
  if (dir_path == NULL) {
    return -1;
  }

  int result = 0;
  size_t len = strlen(dir_path);

  // 移除末尾的斜杠（如果不是根目录）
  if (len > 1 && dir_path[len - 1] == '/') {
    dir_path[len - 1] = '\0';
    len--;
  }

  // 逐级创建目录
  for (char* p = dir_path + 1; *p; p++) {
    if (*p == '/') {
      *p = '\0';  // 临时截断字符串

      // 创建当前级别的目录
      if (MKDIR(dir_path, 0755) != 0) {
        // 如果目录已存在则忽略错误，否则返回错误
        if (errno != EEXIST) {
          result = -1;
          break;
        }
      }

      *p = '/';  // 恢复字符串
    }
  }

  // 创建最终目录
  if (result == 0) {
    if (MKDIR(dir_path, 0755) != 0 && errno != EEXIST) {
      result = -1;
    }
  }

  free(dir_path);
  return result;
}

static int __platform_isDir(const char* path) {
  struct stat path_stat;

  // 检查路径是否存在且可访问
  if (stat(path, &path_stat) != 0) {
    return -1;  // 路径不存在或无法访问
  }

  // 检查是否为目录
  if (S_ISDIR(path_stat.st_mode)) {
    return 0;  // 是目录
  }

  return -1;  // 不是目录
}

static time_t __platform_time(const char* path) {
  struct stat path_stat;

  // 检查路径是否存在且可访问
  if (stat(path, &path_stat) != 0) {
    return -1;  // 路径不存在或无法访问
  }

  // 返回最后修改时间
  return path_stat.st_mtime;
}

static int __platform_getname(const char* path, char* result, size_t size) {
  if (path == NULL || result == NULL) {
    return -1;
  }
  // 查找路径中最后一个 '/' 字符的位置
  const char* last_slash = strrchr(path, '/');

  const char* filename;
  if (last_slash != NULL) {
    // 如果找到了 '/'，则文件名是 '/' 后面的部分
    filename = last_slash + 1;
  } else {
    // 如果没有找到 '/'，则整个路径就是文件名
    filename = path;
  }

  // 计算文件名长度
  size_t filename_len = strlen(filename);
  if (filename_len >= size) {
    return -1;
  }
  // 使用安全的字符串复制函数
  snprintf(result, filename_len + 1, "%s", filename);
  return 0;
}

static int __platform_getext(const char* path, char* result, size_t size) {
  if (path == NULL || result == NULL) {
    return -1;
  }

  // 首先获取文件名（不包含路径）
  const char* last_slash = strrchr(path, '/');
  const char* filename;
  if (last_slash != NULL) {
    filename = last_slash + 1;
  } else {
    filename = path;
  }

  // 查找文件名中最后一个 '.' 字符的位置
  const char* last_dot = strrchr(filename, '.');

  // 如果找到了 '.' 且不是第一个字符（避免隐藏文件被误判）
  if (last_dot != NULL && last_dot != filename) {
    // 计算扩展名长度（包含 '.'）
    size_t ext_len = strlen(last_dot);

    // 检查缓冲区大小是否足够
    if (ext_len >= size) {
      return -1;
    }

    // 使用安全的字符串复制函数
    snprintf(result, size, "%s", last_dot);
  } else {
    // 没有扩展名，返回空字符串
    if (size < 1) {
      return -1;
    }
    result[0] = '\0';
  }

  return 0;
}

static int __platform_getpath(const char* path, char* result, size_t size) {
  if (path == NULL || result == NULL || size == 0) {
    return -1;
  }

  // 查找路径中最后一个 '/' 字符的位置
  const char* last_slash = strrchr(path, '/');

  if (last_slash != NULL) {
    // 计算目录路径长度（包含最后的 '/'）
    size_t dir_len = last_slash - path + 1;

    // 检查缓冲区大小是否足够
    if (dir_len >= size) {
      return -1;
    }

    // 使用安全的字符串复制函数
    snprintf(result, size, "%.*s", (int)dir_len, path);
  } else {
    // 没有找到 '/'，表示当前目录，使用 "./" 格式
    if (size < 3) {
      return -1;
    }
    result[0] = '.';
    result[1] = '/';
    result[2] = '\0';
  }

  return 0;
}
#endif

#undef _POSIX_C_SOURCE
#undef _GNU_SOURCE

#endif